
#include "gen_halfedge.h"
#include "cgal_defines.hpp"

#include <CGAL/Aff_transformation_3.h>
#include <CGAL/Distance_3/Point_3_Line_3.h>
#include <CGAL/Homogeneous/DirectionH3.h>

#include <cassert>
#include <cmath>
#include <stdexcept>
#include <vector>

std::vector<point_type>
cgalView::gen_halfedge::gen(point_type const &start, point_type const &end,
                            vector_type const &normal_face) {
  if (start == end) {
    throw std::invalid_argument{"start == end."};
  }

  vector_type vector_of_edge{start, end};
  vector_of_edge /= std::sqrt(vector_of_edge.squared_length());
  auto normal_of_face = normal_face / std::sqrt(normal_face.squared_length());
  auto normal_of_edge = CGAL::cross_product(normal_of_face, vector_of_edge);
  normal_of_edge /= std::sqrt(normal_of_edge.squared_length());

  auto pnt = start + normal_of_edge * this->d_halfedge_offset;
  auto pnt1 = pnt + vector_of_edge * (4 * this->d_halfedge_offset);

  auto len = std::sqrt(CGAL::squared_distance(start, end));
  auto pnt2 = pnt + vector_of_edge * (len - 4 * this->d_halfedge_offset);

  auto radian = 3.1415926 / 180 * this->d_angle_arrow;
  auto len_l1 = this->d_length_arrow * std::cos(radian);
  auto len_l2 = this->d_length_arrow * std::sin(radian);

  point_type pnt3{};
  {
    auto pnt_l1 = pnt2 - vector_of_edge * len_l1;
    auto pnt_l2 = pnt_l1 + normal_of_edge * len_l2;

    vector_type vec_l1{pnt2, pnt_l1};
    vector_type vec_l2{pnt_l1, pnt_l2};
    auto vec = vec_l1 + vec_l2;
    pnt3 = pnt2 + vec;
  }

  return {pnt1, pnt2, pnt3};
}